// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <pollux/functions/lib/subscript_util.h>

namespace kumo::pollux::functions {

namespace {

/// Subscript operator for arrays and maps (to be mapped from usages like
/// array[0] and map['key']).
/// - does not allow negative indices for arrays
/// - does not allow out of bounds accesses for arrays (throws)
/// - index starts at 1 for arrays.
class SubscriptFunction : public SubscriptImpl<
                              /* allowNegativeIndices */ false,
                              /* nullOnNegativeIndices */ false,
                              /* allowOutOfBound */ false,
                              /* indexStartsAtOne */ true> {
 public:
  explicit SubscriptFunction(bool allowcaching) : SubscriptImpl(allowcaching) {}

  bool canPushdown() const override {
    return true;
  }
};

} // namespace

void registerSubscriptFunction(
    const std::string& name,
    bool enableCaching = true) {
  exec::registerStatefulVectorFunction(
      name,
      SubscriptFunction::signatures(),
      [enableCaching](
          const std::string&,
          const std::vector<exec::VectorFunctionArg>& inputArgs,
          const pollux::core::QueryConfig& config) {
        static const auto kSubscriptStateLess =
            std::make_shared<SubscriptFunction>(false);
        if (inputArgs[0].type->is_array()) {
          return kSubscriptStateLess;
        } else {
          return std::make_shared<SubscriptFunction>(
              enableCaching && config.isExpressionEvaluationCacheEnabled());
        }
      });
}

} // namespace kumo::pollux::functions
